
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dio/dio.dart';
import 'package:flutter_getx/app/base/state_layout.dart';
import 'package:flutter_getx/app/config/constant.dart';
import 'package:flutter_getx/core/getx/control/state/base_state.dart';
import 'package:flutter_getx/core/net/net.dart';
import 'package:flutter_getx/core/utils/log_utils.dart';
import 'package:flutter_getx/core/utils/show_utils.dart';

import 'i_controller_delegate.dart';

class DioDelegate implements IControllerDelegate {

  bool isClose = false;
  late CancelToken _cancelToken;

  @override
  void onClose() {
    isClose = true;
    if (!_cancelToken.isCancelled) {
      _cancelToken.cancel();
    }
  }

  @override
  void onInit() {
    _cancelToken = CancelToken();
  }

  @override
  void onReady() {

  }


  /// 返回Future 适用于刷新，加载更多
  Future request<T>(Method method, {
    required String url,
    bool isShow = false,
    bool isClose = true,
    NetSuccessCallback<T?>? onSuccess,
    NetErrorCallback? onError,
    dynamic params,
    Map<String, dynamic>? queryParameters,
    CancelToken? cancelToken,
    Options? options,
    BaseState? state,
  }) {
    if (isShow) {
      showLoading();
    }
    return DioUtils.instance.requestNetwork<T>(method, url,
      params: params,
      queryParameters: queryParameters,
      options: options,
      cancelToken: cancelToken?? _cancelToken,
      onSuccess: (data) {
        if (isClose) {
          dismissSmart(closeType: CloseType.Loading);
        }

        if(Constant.inProduction) {
          try {
            onSuccess?.call(data);
          } catch (e) {
            lprinte("Request url = $url \nUnhandled Exception: ${e.toString()}");
            _onError(ExceptionHandle.handle_error, ExceptionHandle.getNetError(ExceptionHandle.handle_error).msg, onError, state);
          }
        } else{
          //debug 时 不主动捕获错误，方便查看错误信息
          onSuccess?.call(data);
        }
      },
      onError: (code, msg) {
        _onError(code, msg, onError, state);
      },
    );
  }

  void asyncRequest<T>(Method method, {
    required String url,
    bool isShow = false,
    bool isClose = true,
    NetSuccessCallback<T?>? onSuccess,
    NetErrorCallback? onError,
    dynamic params,
    Map<String, dynamic>? queryParameters,
    CancelToken? cancelToken,
    Options? options,
    BaseState? state,
  }) {
    if (isShow) {
      showLoading();
    }
    DioUtils.instance.asyncRequestNetwork<T>(method, url,
      params: params,
      queryParameters: queryParameters,
      options: options,
      cancelToken: cancelToken?? _cancelToken,
      onSuccess: (data) {
        if (isClose) {
          dismissSmart(closeType: CloseType.Loading);
        }
        if(Constant.inProduction) {
          try {
            onSuccess?.call(data);
          } catch (e) {
            LogPrint.e("Request url = $url \nUnhandled Exception: ${e.toString()}");
            _onError(ExceptionHandle.handle_error, ExceptionHandle.getNetError(ExceptionHandle.handle_error).msg, onError, state);
          }
        } else{
          //debug 时 不主动捕获错误，方便查看错误信息
          onSuccess?.call(data);
        }
      },
      onError: (code, msg) {
        _onError(code, msg, onError, state);
      },
    );
  }

  /// 上传图片实现
  /*Future<String> uploadImg(File image) async {
    String imgPath = '';
    try{
      final String path = image.path;
      final String name = path.substring(path.lastIndexOf('/') + 1);
      final FormData formData = FormData.fromMap(<String, dynamic>{
        'uploadIcon': await MultipartFile.fromFile(path, filename: name)
      });
      await request<String>(Method.post,
          url: api_upload,
          params: formData,
          onSuccess: (data) {
            imgPath = data ?? '';
          }
      );
    } catch(e) {
      toast('image upload failed');
    }
    return imgPath;
  }*/

  Future<void> _onError(int code, String msg, NetErrorCallback? onError, BaseState? state) async{
    /// 页面如果dispose，则不回调onError
    if(!isClose) {
      /// 异常时直接关闭加载圈，不受isClose影响
      dismissSmart(closeType: CloseType.Loading);
      if (code != ExceptionHandle.cancel_error && onError == null) {
        toast(msg);
      }

      if (onError != null) {
        onError(code, msg);
      }

      if (null != state) {
        var connectivityResult = await (Connectivity().checkConnectivity());
        if (connectivityResult == ConnectivityResult.none) {
          state.stateType.value = StateType.noNetwork;
        } else {
          state.stateType.value = StateType.error;
        }
      }
    }
  }

}